using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Collections.Specialized;
namespace Deloitte.Windows.Controls
{
	/// <summary>
	/// Summary description for ControlDataViewRowFilter.
	/// </summary>
	public class DataViewFilterControl : System.Windows.Forms.UserControl
	{        
		private DataView dataView;        
        private Button filterButton;
        private Button removeFilterButton;
        private DataGridView statementGridView;
        private NameValueCollection columnMapping;
        private DataGridViewComboBoxColumn columnNamesColumn;
        private DataGridViewComboBoxColumn operatorColumn;
        private DataGridViewTextBoxColumn valueColumn;
        private DataGridViewComboBoxColumn andOrColumn;
		/// <summary> 
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public DataViewFilterControl(DataView dv)
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			CommonConstructorCode();
            this.SetDataView(dv);            
		}
        public DataViewFilterControl(DataView dv, NameValueCollection colMapping)
        {
            // This call is required by the Windows.Forms Form Designer.
            InitializeComponent();
            CommonConstructorCode();
            this.SetDataView(dv, colMapping);
        }
        public DataViewFilterControl()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();			
			CommonConstructorCode();					
		}
		public DataView DataView
		{
			get{return this.dataView;}			
		}
		private void CommonConstructorCode()
		{
           
		}
        public void SetDataView(DataView dv)
        {
            this.dataView = dv;
            this.SetColumnNames();
        }
        public void SetDataView(DataView dv, NameValueCollection colMapping)
        {
            this.dataView = dv;
            this.columnMapping = colMapping;
            this.SetColumnNames(colMapping);            
        }
        private void SetColumnNames(NameValueCollection columnMapping)
        {
            this.columnNamesColumn.Items.Clear();
            int i = 0;
            if (columnMapping == null)
            {
                object[] columnNames = new object[this.dataView.Table.Columns.Count];                                
                this.columnNamesColumn.Items.AddRange(columnNames);
            }
            else
            {
                object[] columnNames = new object[columnMapping.Count];
                foreach (string key in columnMapping.Keys)
                {
                    columnNames[i] = key;
                    i++;
                }
                this.columnNamesColumn.Items.AddRange(columnNames);
            }
        }

        private void SetColumnNames()
        {
            this.columnMapping = new NameValueCollection(this.dataView.Table.Columns.Count);
            foreach (DataColumn col in this.dataView.Table.Columns)
            {
                this.columnMapping.Add(col.ColumnName, col.ColumnName);
            }
            this.SetColumnNames(columnMapping);
        }

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
            this.filterButton = new System.Windows.Forms.Button();
            this.removeFilterButton = new System.Windows.Forms.Button();
            this.statementGridView = new System.Windows.Forms.DataGridView();
            this.columnNamesColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
            this.operatorColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
            this.valueColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
            this.andOrColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
            ((System.ComponentModel.ISupportInitialize)(this.statementGridView)).BeginInit();
            this.SuspendLayout();
            // 
            // filterButton
            // 
            this.filterButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.filterButton.AutoSize = true;
            this.filterButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            this.filterButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.filterButton.Location = new System.Drawing.Point(8, 154);
            this.filterButton.Name = "filterButton";
            this.filterButton.Size = new System.Drawing.Size(38, 24);
            this.filterButton.TabIndex = 30;
            this.filterButton.Text = "&Filter";
            this.filterButton.UseVisualStyleBackColor = true;
            this.filterButton.Click += new System.EventHandler(this.filterButton_Click);
            // 
            // removeFilterButton
            // 
            this.removeFilterButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.removeFilterButton.AutoSize = true;
            this.removeFilterButton.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            this.removeFilterButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.removeFilterButton.Location = new System.Drawing.Point(57, 154);
            this.removeFilterButton.Name = "removeFilterButton";
            this.removeFilterButton.Size = new System.Drawing.Size(76, 24);
            this.removeFilterButton.TabIndex = 31;
            this.removeFilterButton.Text = "&Remove Filter";
            this.removeFilterButton.UseVisualStyleBackColor = true;
            this.removeFilterButton.Click += new System.EventHandler(this.removeFilterButton_Click);
            // 
            // statementGridView
            // 
            this.statementGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.statementGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.statementGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
            this.columnNamesColumn,
            this.operatorColumn,
            this.valueColumn,
            this.andOrColumn});
            dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
            dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
            dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F);
            dataGridViewCellStyle1.ForeColor = System.Drawing.Color.Black;
            dataGridViewCellStyle1.SelectionBackColor = System.Drawing.Color.Gray;
            dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
            dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
            this.statementGridView.DefaultCellStyle = dataGridViewCellStyle1;
            this.statementGridView.Location = new System.Drawing.Point(8, 8);
            this.statementGridView.Name = "statementGridView";
            this.statementGridView.Size = new System.Drawing.Size(456, 139);
            this.statementGridView.TabIndex = 32;
            // 
            // columnNamesColumn
            // 
            this.columnNamesColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
            this.columnNamesColumn.HeaderText = "Column";
            this.columnNamesColumn.MaxDropDownItems = 50;
            this.columnNamesColumn.MinimumWidth = 120;
            this.columnNamesColumn.Name = "columnNamesColumn";
            this.columnNamesColumn.Width = 120;
            // 
            // operatorColumn
            // 
            this.operatorColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
            this.operatorColumn.HeaderText = "Operator";
            this.operatorColumn.Items.AddRange(new object[] {
            "=",
            "<>",
            "<",
            ">",
            "<=",
            ">=",
            "LIKE",
            "NOT LIKE",
            "BETWEEN",
            "NOT BETWEEN",
            "IN",
            "NOT IN"});
            this.operatorColumn.MinimumWidth = 57;
            this.operatorColumn.Name = "operatorColumn";
            this.operatorColumn.Width = 57;
            // 
            // valueColumn
            // 
            this.valueColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
            this.valueColumn.HeaderText = "Value";
            this.valueColumn.MinimumWidth = 150;
            this.valueColumn.Name = "valueColumn";
            this.valueColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
            this.valueColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
            this.valueColumn.Width = 150;
            // 
            // andOrColumn
            // 
            this.andOrColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
            this.andOrColumn.HeaderText = "And/Or";
            this.andOrColumn.Items.AddRange(new object[] {
            "",
            "AND",
            "OR"});
            this.andOrColumn.MinimumWidth = 48;
            this.andOrColumn.Name = "andOrColumn";
            this.andOrColumn.Width = 48;
            // 
            // DataViewFilterControl
            // 
            this.AutoScroll = true;
            this.Controls.Add(this.statementGridView);
            this.Controls.Add(this.removeFilterButton);
            this.Controls.Add(this.filterButton);
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F);
            this.ForeColor = System.Drawing.Color.Black;
            this.Name = "DataViewFilterControl";
            this.Size = new System.Drawing.Size(472, 181);
            ((System.ComponentModel.ISupportInitialize)(this.statementGridView)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion
						
		private string GetFilterStatement()
		{
			DataGridViewRow dr=null;
			string myOperator, colName, andOr, myValue;
			System.Type thisDataType;
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			for(int i =0;i<this.statementGridView.Rows.Count -1;i++)
			{
                dr = this.statementGridView.Rows[i];
                colName = this.columnMapping[dr.Cells[0].Value.ToString()];
                myOperator = dr.Cells[1].Value.ToString();
                myValue = dr.Cells[2].Value.ToString();
                if (dr.Cells[3].Value != null) { andOr = dr.Cells[3].Value.ToString(); }
                else { andOr = string.Empty; }
				thisDataType = this.dataView.Table.Columns[colName].DataType;
				if(isValidOperator(myOperator, thisDataType))
				{
					sb.Append("[" + colName + "]");
					sb.Append(" " + myOperator + " ");
					if (thisDataType == typeof(string))
					{	
						if(myOperator=="IN")sb.Append(" " + myValue + " ");
                        else if (myOperator == "LIKE" && myValue.IndexOf("%") == -1)
                        {
                            { sb.Append("'%" + myValue + "%'"); }
                        }
                        else { sb.Append("'" + myValue + "'"); }
					}
					else if(thisDataType.FullName.IndexOf("Date") != -1)
					{
						//todo: fix the between statement
						if(myOperator=="BETWEEN")sb.Append(" " + myValue + " ");
						else{sb.Append("#" + myValue + "#");}
					}
					else 
					{
						sb.Append(" " + myValue + " ");
					}
                    if (i < this.statementGridView.Rows.Count - 2) sb.Append(" " + andOr + " ");
				}
				else
				{
					MessageBox.Show("Error in the filter statement");
					return null;
					//todo: display the error control with
				}
				//todo: implement filter statement logic
			}			
			return sb.ToString();//"[" + this.myDataView.Table.Columns[0].ColumnName + "] LIKE " + "'C%'";
		}
		private bool isValidOperator(string thisOperator, System.Type thisDataType)
		{
			string[] stringOps = {"=", "<>", "LIKE", "!=", "IN", "NOT LIKE", "NOT IN"};
			string[] dateOps = {"=", "<>", "BETWEEN", "NOT BETWEEN", "!=", ">", ">=", "<", "<="};
			string[] numOps = {"IN", "LIKE", "BETWEEN", "NOT BETWEEN"};
			//todo: code other data types here, also add an error table.  
			//we may want to add a generic error control to display errors.
			if (thisDataType==typeof(string))
			{								
				if(Array.IndexOf(stringOps, thisOperator) == -1)return false;
				else{return true;}
			}
            else if (thisDataType.FullName.IndexOf("DateTime") != -1)
            {
                if (Array.IndexOf(dateOps, thisOperator) == -1) return false;
                else { return true; }
            }
			else if(thisDataType.FullName.IndexOf("Date") != -1)
			{
				if(Array.IndexOf(dateOps, thisOperator) == -1)return false;
				else{return true;}
			}
			else {
				if(Array.IndexOf(numOps, thisOperator) == -1)return true;
				else{return false;}
			}			               			
		}

        private void filterButton_Click(object sender, EventArgs e)
        {
            string filterStatement = null;
            try
            {
                filterStatement = GetFilterStatement();
                this.DataView.RowFilter = filterStatement;
            }
            catch (System.Data.EvaluateException exEE) { MessageBox.Show(("The expression:\n" + filterStatement + "\n could not be evaluated.\n\n" + exEE.Message)); }
            catch (System.Data.SyntaxErrorException exSEE) { MessageBox.Show(("The expression:\n" + filterStatement + "\n could not be evaluated.\n\n" + exSEE.Message)); }
            catch (Exception ex) { MessageBox.Show(ex.ToString()); }
        }

        private void removeFilterButton_Click(object sender, EventArgs e)
        {
            if (this.dataView != null )this.DataView.RowFilter = string.Empty;
        }

    }
}
